1 /*
2 * Copyright (C) 2009 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.google.common.collect;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 import static com.google.common.collect.Maps.keyOrNull;
22
23 import com.google.common.annotations.GwtCompatible;
24
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.Comparator;
28 import java.util.Map;
29 import java.util.NavigableMap;
30 import java.util.SortedMap;
31 import java.util.TreeMap;
32
33 import javax.annotation.Nullable;
34
35 /**
36 * An immutable {@link SortedMap}. Does not permit null keys or values.
37 *
38 * <p>Unlike {@link Collections#unmodifiableSortedMap}, which is a <i>view</i>
39 * of a separate map which can still change, an instance of {@code
40 * ImmutableSortedMap} contains its own data and will <i>never</i> change.
41 * {@code ImmutableSortedMap} is convenient for {@code public static final} maps
42 * ("constant maps") and also lets you easily make a "defensive copy" of a map
43 * provided to your class by a caller.
44 *
45 * <p><b>Note:</b> Although this class is not final, it cannot be subclassed as
46 * it has no public or protected constructors. Thus, instances of this class are
47 * guaranteed to be immutable.
48 *
49 * <p>See the Guava User Guide article on <a href=
50 * "http://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained">
51 * immutable collections</a>.
52 *
53 * @author Jared Levy
54 * @author Louis Wasserman
55 * @since 2.0 (imported from Google Collections Library; implements {@code
56 * NavigableMap} since 12.0)
57 */
58 @GwtCompatible(serializable = true, emulated = true)
59 public abstract class ImmutableSortedMap<K, V>
60 extends ImmutableSortedMapFauxverideShim<K, V> implements NavigableMap<K, V> {
61 /*
62 * TODO(kevinb): Confirm that ImmutableSortedMap is faster to construct and
63 * uses less memory than TreeMap; then say so in the class Javadoc.
64 */
65 private static final Comparator<Comparable> NATURAL_ORDER = Ordering.natural();
66
67 private static final ImmutableSortedMap<Comparable, Object> NATURAL_EMPTY_MAP =
68 new EmptyImmutableSortedMap<Comparable, Object>(NATURAL_ORDER);
69
70 static <K, V> ImmutableSortedMap<K, V> emptyMap(Comparator<? super K> comparator) {
71 if (Ordering.natural().equals(comparator)) {
72 return of();
73 } else {
74 return new EmptyImmutableSortedMap<K, V>(comparator);
75 }
76 }
77
78 static <K, V> ImmutableSortedMap<K, V> fromSortedEntries(
79 Comparator<? super K> comparator,
80 int size,
81 Entry<K, V>[] entries) {
82 if (size == 0) {
83 return emptyMap(comparator);
84 }
85
86 ImmutableList.Builder<K> keyBuilder = ImmutableList.builder();
87 ImmutableList.Builder<V> valueBuilder = ImmutableList.builder();
88 for (int i = 0; i < size; i++) {
89 Entry<K, V> entry = entries[i];
90 keyBuilder.add(entry.getKey());
91 valueBuilder.add(entry.getValue());
92 }
93
94 return new RegularImmutableSortedMap<K, V>(
95 new RegularImmutableSortedSet<K>(keyBuilder.build(), comparator),
96 valueBuilder.build());
97 }
98
99 static <K, V> ImmutableSortedMap<K, V> from(
100 ImmutableSortedSet<K> keySet, ImmutableList<V> valueList) {
101 if (keySet.isEmpty()) {
102 return emptyMap(keySet.comparator());
103 } else {
104 return new RegularImmutableSortedMap<K, V>(
105 (RegularImmutableSortedSet<K>) keySet,
106 valueList);
107 }
108 }
109
110 /**
111 * Returns the empty sorted map.
112 */
113 @SuppressWarnings("unchecked")
114 // unsafe, comparator() returns a comparator on the specified type
115 // TODO(kevinb): evaluate whether or not of().comparator() should return null
116 public static <K, V> ImmutableSortedMap<K, V> of() {
117 return (ImmutableSortedMap<K, V>) NATURAL_EMPTY_MAP;
118 }
119
120 /**
121 * Returns an immutable map containing a single entry.
122 */
123 public static <K extends Comparable<? super K>, V>
124 ImmutableSortedMap<K, V> of(K k1, V v1) {
125 return from(ImmutableSortedSet.of(k1), ImmutableList.of(v1));
126 }
127
128 /**
129 * Returns an immutable sorted map containing the given entries, sorted by the
130 * natural ordering of their keys.
131 *
132 * @throws IllegalArgumentException if the two keys are equal according to
133 * their natural ordering
134 */
135 @SuppressWarnings("unchecked")
136 public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
137 of(K k1, V v1, K k2, V v2) {
138 return fromEntries(Ordering.natural(), false, 2, entryOf(k1, v1), entryOf(k2, v2));
139 }
140
141 /**
142 * Returns an immutable sorted map containing the given entries, sorted by the
143 * natural ordering of their keys.
144 *
145 * @throws IllegalArgumentException if any two keys are equal according to
146 * their natural ordering
147 */
148 @SuppressWarnings("unchecked")
149 public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
150 of(K k1, V v1, K k2, V v2, K k3, V v3) {
151 return fromEntries(Ordering.natural(), false, 3, entryOf(k1, v1), entryOf(k2, v2),
152 entryOf(k3, v3));
153 }
154
155 /**
156 * Returns an immutable sorted map containing the given entries, sorted by the
157 * natural ordering of their keys.
158 *
159 * @throws IllegalArgumentException if any two keys are equal according to
160 * their natural ordering
161 */
162 @SuppressWarnings("unchecked")
163 public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
164 of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
165 return fromEntries(Ordering.natural(), false, 4, entryOf(k1, v1), entryOf(k2, v2),
166 entryOf(k3, v3), entryOf(k4, v4));
167 }
168
169 /**
170 * Returns an immutable sorted map containing the given entries, sorted by the
171 * natural ordering of their keys.
172 *
173 * @throws IllegalArgumentException if any two keys are equal according to
174 * their natural ordering
175 */
176 @SuppressWarnings("unchecked")
177 public static <K extends Comparable<? super K>, V> ImmutableSortedMap<K, V>
178 of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
179 return fromEntries(Ordering.natural(), false, 5, entryOf(k1, v1), entryOf(k2, v2),
180 entryOf(k3, v3), entryOf(k4, v4), entryOf(k5, v5));
181 }
182
183 /**
184 * Returns an immutable map containing the same entries as {@code map}, sorted
185 * by the natural ordering of the keys.
186 *
187 * <p>Despite the method name, this method attempts to avoid actually copying
188 * the data when it is safe to do so. The exact circumstances under which a
189 * copy will or will not be performed are undocumented and subject to change.
190 *
191 * <p>This method is not type-safe, as it may be called on a map with keys
192 * that are not mutually comparable.
193 *
194 * @throws ClassCastException if the keys in {@code map} are not mutually
195 * comparable
196 * @throws NullPointerException if any key or value in {@code map} is null
197 * @throws IllegalArgumentException if any two keys are equal according to
198 * their natural ordering
199 */
200 public static <K, V> ImmutableSortedMap<K, V> copyOf(
201 Map<? extends K, ? extends V> map) {
202 // Hack around K not being a subtype of Comparable.
203 // Unsafe, see ImmutableSortedSetFauxverideShim.
204 @SuppressWarnings("unchecked")
205 Ordering<K> naturalOrder = (Ordering<K>) Ordering.<Comparable>natural();
206 return copyOfInternal(map, naturalOrder);
207 }
208
209 /**
210 * Returns an immutable map containing the same entries as {@code map}, with
211 * keys sorted by the provided comparator.
212 *
213 * <p>Despite the method name, this method attempts to avoid actually copying
214 * the data when it is safe to do so. The exact circumstances under which a
215 * copy will or will not be performed are undocumented and subject to change.
216 *
217 * @throws NullPointerException if any key or value in {@code map} is null
218 * @throws IllegalArgumentException if any two keys are equal according to the
219 * comparator
220 */
221 public static <K, V> ImmutableSortedMap<K, V> copyOf(
222 Map<? extends K, ? extends V> map, Comparator<? super K> comparator) {
223 return copyOfInternal(map, checkNotNull(comparator));
224 }
225
226 /**
227 * Returns an immutable map containing the same entries as the provided sorted
228 * map, with the same ordering.
229 *
230 * <p>Despite the method name, this method attempts to avoid actually copying
231 * the data when it is safe to do so. The exact circumstances under which a
232 * copy will or will not be performed are undocumented and subject to change.
233 *
234 * @throws NullPointerException if any key or value in {@code map} is null
235 */
236 @SuppressWarnings("unchecked")
237 public static <K, V> ImmutableSortedMap<K, V> copyOfSorted(
238 SortedMap<K, ? extends V> map) {
239 Comparator<? super K> comparator = map.comparator();
240 if (comparator == null) {
241 // If map has a null comparator, the keys should have a natural ordering,
242 // even though K doesn't explicitly implement Comparable.
243 comparator = (Comparator<? super K>) NATURAL_ORDER;
244 }
245 return copyOfInternal(map, comparator);
246 }
247
248 private static <K, V> ImmutableSortedMap<K, V> copyOfInternal(
249 Map<? extends K, ? extends V> map, Comparator<? super K> comparator) {
250 boolean sameComparator = false;
251 if (map instanceof SortedMap) {
252 SortedMap<?, ?> sortedMap = (SortedMap<?, ?>) map;
253 Comparator<?> comparator2 = sortedMap.comparator();
254 sameComparator = (comparator2 == null)
255 ? comparator == NATURAL_ORDER
256 : comparator.equals(comparator2);
257 }
258
259 if (sameComparator && (map instanceof ImmutableSortedMap)) {
260 // TODO(kevinb): Prove that this cast is safe, even though
261 // Collections.unmodifiableSortedMap requires the same key type.
262 @SuppressWarnings("unchecked")
263 ImmutableSortedMap<K, V> kvMap = (ImmutableSortedMap<K, V>) map;
264 if (!kvMap.isPartialView()) {
265 return kvMap;
266 }
267 }
268
269 // "adding" type params to an array of a raw type should be safe as
270 // long as no one can ever cast that same array instance back to a
271 // raw type.
272 @SuppressWarnings("unchecked")
273 Entry<K, V>[] entries = map.entrySet().toArray(new Entry[0]);
274
275 return fromEntries(comparator, sameComparator, entries.length, entries);
276 }
277
278 static <K, V> ImmutableSortedMap<K, V> fromEntries(
279 Comparator<? super K> comparator, boolean sameComparator, int size, Entry<K, V>... entries) {
280 for (int i = 0; i < size; i++) {
281 Entry<K, V> entry = entries[i];
282 entries[i] = entryOf(entry.getKey(), entry.getValue());
283 }
284 if (!sameComparator) {
285 sortEntries(comparator, size, entries);
286 validateEntries(size, entries, comparator);
287 }
288
289 return fromSortedEntries(comparator, size, entries);
290 }
291
292 private static <K, V> void sortEntries(
293 final Comparator<? super K> comparator, int size, Entry<K, V>[] entries) {
294 Arrays.sort(entries, 0, size, Ordering.from(comparator).<K>onKeys());
295 }
296
297 private static <K, V> void validateEntries(int size, Entry<K, V>[] entries,
298 Comparator<? super K> comparator) {
299 for (int i = 1; i < size; i++) {
300 checkNoConflict(comparator.compare(entries[i - 1].getKey(), entries[i].getKey()) != 0, "key",
301 entries[i - 1], entries[i]);
302 }
303 }
304
305 /**
306 * Returns a builder that creates immutable sorted maps whose keys are
307 * ordered by their natural ordering. The sorted maps use {@link
308 * Ordering#natural()} as the comparator.
309 */
310 public static <K extends Comparable<?>, V> Builder<K, V> naturalOrder() {
311 return new Builder<K, V>(Ordering.natural());
312 }
313
314 /**
315 * Returns a builder that creates immutable sorted maps with an explicit
316 * comparator. If the comparator has a more general type than the map's keys,
317 * such as creating a {@code SortedMap<Integer, String>} with a {@code
318 * Comparator<Number>}, use the {@link Builder} constructor instead.
319 *
320 * @throws NullPointerException if {@code comparator} is null
321 */
322 public static <K, V> Builder<K, V> orderedBy(Comparator<K> comparator) {
323 return new Builder<K, V>(comparator);
324 }
325
326 /**
327 * Returns a builder that creates immutable sorted maps whose keys are
328 * ordered by the reverse of their natural ordering.
329 */
330 public static <K extends Comparable<?>, V> Builder<K, V> reverseOrder() {
331 return new Builder<K, V>(Ordering.natural().reverse());
332 }
333
334 /**
335 * A builder for creating immutable sorted map instances, especially {@code
336 * public static final} maps ("constant maps"). Example: <pre> {@code
337 *
338 * static final ImmutableSortedMap<Integer, String> INT_TO_WORD =
339 * new ImmutableSortedMap.Builder<Integer, String>(Ordering.natural())
340 * .put(1, "one")
341 * .put(2, "two")
342 * .put(3, "three")
343 * .build();}</pre>
344 *
345 * <p>For <i>small</i> immutable sorted maps, the {@code ImmutableSortedMap.of()}
346 * methods are even more convenient.
347 *
348 * <p>Builder instances can be reused - it is safe to call {@link #build}
349 * multiple times to build multiple maps in series. Each map is a superset of
350 * the maps created before it.
351 *
352 * @since 2.0 (imported from Google Collections Library)
353 */
354 public static class Builder<K, V> extends ImmutableMap.Builder<K, V> {
355 private final Comparator<? super K> comparator;
356
357 /**
358 * Creates a new builder. The returned builder is equivalent to the builder
359 * generated by {@link ImmutableSortedMap#orderedBy}.
360 */
361 @SuppressWarnings("unchecked")
362 public Builder(Comparator<? super K> comparator) {
363 this.comparator = checkNotNull(comparator);
364 }
365
366 /**
367 * Associates {@code key} with {@code value} in the built map. Duplicate
368 * keys, according to the comparator (which might be the keys' natural
369 * order), are not allowed, and will cause {@link #build} to fail.
370 */
371 @Override public Builder<K, V> put(K key, V value) {
372 super.put(key, value);
373 return this;
374 }
375
376 /**
377 * Adds the given {@code entry} to the map, making it immutable if
378 * necessary. Duplicate keys, according to the comparator (which might be
379 * the keys' natural order), are not allowed, and will cause {@link #build}
380 * to fail.
381 *
382 * @since 11.0
383 */
384 @Override public Builder<K, V> put(Entry<? extends K, ? extends V> entry) {
385 super.put(entry);
386 return this;
387 }
388
389 /**
390 * Associates all of the given map's keys and values in the built map.
391 * Duplicate keys, according to the comparator (which might be the keys'
392 * natural order), are not allowed, and will cause {@link #build} to fail.
393 *
394 * @throws NullPointerException if any key or value in {@code map} is null
395 */
396 @Override public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
397 super.putAll(map);
398 return this;
399 }
400
401 /**
402 * Returns a newly-created immutable sorted map.
403 *
404 * @throws IllegalArgumentException if any two keys are equal according to
405 * the comparator (which might be the keys' natural order)
406 */
407 @Override public ImmutableSortedMap<K, V> build() {
408 return fromEntries(comparator, false, size, entries);
409 }
410 }
411
412 ImmutableSortedMap() {
413 }
414
415 ImmutableSortedMap(ImmutableSortedMap<K, V> descendingMap) {
416 this.descendingMap = descendingMap;
417 }
418
419 @Override
420 public int size() {
421 return values().size();
422 }
423
424 @Override public boolean containsValue(@Nullable Object value) {
425 return values().contains(value);
426 }
427
428 @Override boolean isPartialView() {
429 return keySet().isPartialView() || values().isPartialView();
430 }
431
432 /**
433 * Returns an immutable set of the mappings in this map, sorted by the key
434 * ordering.
435 */
436 @Override public ImmutableSet<Entry<K, V>> entrySet() {
437 return super.entrySet();
438 }
439
440 /**
441 * Returns an immutable sorted set of the keys in this map.
442 */
443 @Override public abstract ImmutableSortedSet<K> keySet();
444
445 /**
446 * Returns an immutable collection of the values in this map, sorted by the
447 * ordering of the corresponding keys.
448 */
449 @Override public abstract ImmutableCollection<V> values();
450
451 /**
452 * Returns the comparator that orders the keys, which is
453 * {@link Ordering#natural()} when the natural ordering of the keys is used.
454 * Note that its behavior is not consistent with {@link TreeMap#comparator()},
455 * which returns {@code null} to indicate natural ordering.
456 */
457 @Override
458 public Comparator<? super K> comparator() {
459 return keySet().comparator();
460 }
461
462 @Override
463 public K firstKey() {
464 return keySet().first();
465 }
466
467 @Override
468 public K lastKey() {
469 return keySet().last();
470 }
471
472 /**
473 * This method returns a {@code ImmutableSortedMap}, consisting of the entries
474 * whose keys are less than {@code toKey}.
475 *
476 * <p>The {@link SortedMap#headMap} documentation states that a submap of a
477 * submap throws an {@link IllegalArgumentException} if passed a {@code toKey}
478 * greater than an earlier {@code toKey}. However, this method doesn't throw
479 * an exception in that situation, but instead keeps the original {@code
480 * toKey}.
481 */
482 @Override
483 public ImmutableSortedMap<K, V> headMap(K toKey) {
484 return headMap(toKey, false);
485 }
486
487 /**
488 * This method returns a {@code ImmutableSortedMap}, consisting of the entries
489 * whose keys are less than (or equal to, if {@code inclusive}) {@code toKey}.
490 *
491 * <p>The {@link SortedMap#headMap} documentation states that a submap of a
492 * submap throws an {@link IllegalArgumentException} if passed a {@code toKey}
493 * greater than an earlier {@code toKey}. However, this method doesn't throw
494 * an exception in that situation, but instead keeps the original {@code
495 * toKey}.
496 *
497 * @since 12.0
498 */
499 @Override
500 public abstract ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive);
501
502 /**
503 * This method returns a {@code ImmutableSortedMap}, consisting of the entries
504 * whose keys ranges from {@code fromKey}, inclusive, to {@code toKey},
505 * exclusive.
506 *
507 * <p>The {@link SortedMap#subMap} documentation states that a submap of a
508 * submap throws an {@link IllegalArgumentException} if passed a {@code
509 * fromKey} less than an earlier {@code fromKey}. However, this method doesn't
510 * throw an exception in that situation, but instead keeps the original {@code
511 * fromKey}. Similarly, this method keeps the original {@code toKey}, instead
512 * of throwing an exception, if passed a {@code toKey} greater than an earlier
513 * {@code toKey}.
514 */
515 @Override
516 public ImmutableSortedMap<K, V> subMap(K fromKey, K toKey) {
517 return subMap(fromKey, true, toKey, false);
518 }
519
520 /**
521 * This method returns a {@code ImmutableSortedMap}, consisting of the entries
522 * whose keys ranges from {@code fromKey} to {@code toKey}, inclusive or
523 * exclusive as indicated by the boolean flags.
524 *
525 * <p>The {@link SortedMap#subMap} documentation states that a submap of a
526 * submap throws an {@link IllegalArgumentException} if passed a {@code
527 * fromKey} less than an earlier {@code fromKey}. However, this method doesn't
528 * throw an exception in that situation, but instead keeps the original {@code
529 * fromKey}. Similarly, this method keeps the original {@code toKey}, instead
530 * of throwing an exception, if passed a {@code toKey} greater than an earlier
531 * {@code toKey}.
532 *
533 * @since 12.0
534 */
535 @Override
536 public ImmutableSortedMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey,
537 boolean toInclusive) {
538 checkNotNull(fromKey);
539 checkNotNull(toKey);
540 checkArgument(comparator().compare(fromKey, toKey) <= 0,
541 "expected fromKey <= toKey but %s > %s", fromKey, toKey);
542 return headMap(toKey, toInclusive).tailMap(fromKey, fromInclusive);
543 }
544
545 /**
546 * This method returns a {@code ImmutableSortedMap}, consisting of the entries
547 * whose keys are greater than or equals to {@code fromKey}.
548 *
549 * <p>The {@link SortedMap#tailMap} documentation states that a submap of a
550 * submap throws an {@link IllegalArgumentException} if passed a {@code
551 * fromKey} less than an earlier {@code fromKey}. However, this method doesn't
552 * throw an exception in that situation, but instead keeps the original {@code
553 * fromKey}.
554 */
555 @Override
556 public ImmutableSortedMap<K, V> tailMap(K fromKey) {
557 return tailMap(fromKey, true);
558 }
559
560 /**
561 * This method returns a {@code ImmutableSortedMap}, consisting of the entries
562 * whose keys are greater than (or equal to, if {@code inclusive})
563 * {@code fromKey}.
564 *
565 * <p>The {@link SortedMap#tailMap} documentation states that a submap of a
566 * submap throws an {@link IllegalArgumentException} if passed a {@code
567 * fromKey} less than an earlier {@code fromKey}. However, this method doesn't
568 * throw an exception in that situation, but instead keeps the original {@code
569 * fromKey}.
570 *
571 * @since 12.0
572 */
573 @Override
574 public abstract ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive);
575
576 @Override
577 public Entry<K, V> lowerEntry(K key) {
578 return headMap(key, false).lastEntry();
579 }
580
581 @Override
582 public K lowerKey(K key) {
583 return keyOrNull(lowerEntry(key));
584 }
585
586 @Override
587 public Entry<K, V> floorEntry(K key) {
588 return headMap(key, true).lastEntry();
589 }
590
591 @Override
592 public K floorKey(K key) {
593 return keyOrNull(floorEntry(key));
594 }
595
596 @Override
597 public Entry<K, V> ceilingEntry(K key) {
598 return tailMap(key, true).firstEntry();
599 }
600
601 @Override
602 public K ceilingKey(K key) {
603 return keyOrNull(ceilingEntry(key));
604 }
605
606 @Override
607 public Entry<K, V> higherEntry(K key) {
608 return tailMap(key, false).firstEntry();
609 }
610
611 @Override
612 public K higherKey(K key) {
613 return keyOrNull(higherEntry(key));
614 }
615
616 @Override
617 public Entry<K, V> firstEntry() {
618 return isEmpty() ? null : entrySet().asList().get(0);
619 }
620
621 @Override
622 public Entry<K, V> lastEntry() {
623 return isEmpty() ? null : entrySet().asList().get(size() - 1);
624 }
625
626 /**
627 * Guaranteed to throw an exception and leave the map unmodified.
628 *
629 * @throws UnsupportedOperationException always
630 * @deprecated Unsupported operation.
631 */
632 @Deprecated
633 @Override
634 public final Entry<K, V> pollFirstEntry() {
635 throw new UnsupportedOperationException();
636 }
637
638 /**
639 * Guaranteed to throw an exception and leave the map unmodified.
640 *
641 * @throws UnsupportedOperationException always
642 * @deprecated Unsupported operation.
643 */
644 @Deprecated
645 @Override
646 public final Entry<K, V> pollLastEntry() {
647 throw new UnsupportedOperationException();
648 }
649
650 private transient ImmutableSortedMap<K, V> descendingMap;
651
652 @Override
653 public ImmutableSortedMap<K, V> descendingMap() {
654 ImmutableSortedMap<K, V> result = descendingMap;
655 if (result == null) {
656 result = descendingMap = createDescendingMap();
657 }
658 return result;
659 }
660
661 abstract ImmutableSortedMap<K, V> createDescendingMap();
662
663 @Override
664 public ImmutableSortedSet<K> navigableKeySet() {
665 return keySet();
666 }
667
668 @Override
669 public ImmutableSortedSet<K> descendingKeySet() {
670 return keySet().descendingSet();
671 }
672
673 /**
674 * Serialized type for all ImmutableSortedMap instances. It captures the
675 * logical contents and they are reconstructed using public factory methods.
676 * This ensures that the implementation types remain as implementation
677 * details.
678 */
679 private static class SerializedForm extends ImmutableMap.SerializedForm {
680 private final Comparator<Object> comparator;
681 @SuppressWarnings("unchecked")
682 SerializedForm(ImmutableSortedMap<?, ?> sortedMap) {
683 super(sortedMap);
684 comparator = (Comparator<Object>) sortedMap.comparator();
685 }
686 @Override Object readResolve() {
687 Builder<Object, Object> builder = new Builder<Object, Object>(comparator);
688 return createMap(builder);
689 }
690 private static final long serialVersionUID = 0;
691 }
692
693 @Override Object writeReplace() {
694 return new SerializedForm(this);
695 }
696
697 // This class is never actually serialized directly, but we have to make the
698 // warning go away (and suppressing would suppress for all nested classes too)
699 private static final long serialVersionUID = 0;
700 }